package monash.med.crystallography.DatasetTools.DataDepositor;

import fedora.client.FedoraClient;
import fedora.server.management.FedoraAPIM;

import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.RemoteException;
import java.util.ArrayList;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.varia.NullAppender;

/**
 * Datadepositor by Steve Androulakis - Creates an object and uploads datastreams into a Fedora repository
 * <p>
 * Use static method DepositData(String fedoraURL, String fedoraUsername, String fedoraPassword, String METSpath,
			String uploadPath)
 * 
 * @author Steve Androulakis (Monash University)
 * @version 1.0
*/
public class DataDepositor
{
	/**
	 * @param  fedoraURL	Usually follows the form http://example.org:8080/fedora
	 * @param  METSpath The path to the METS xml file describing the object
	 * @param uploadPath The path to the files for ingestion. Is non-recursive to follow the flat structure
	 * of the repository (subdirectories of the path aren't ingested, nor are the files contained within)
	 */
	public static String DepositData(String fedoraURL, String fedoraUsername, String fedoraPassword, String METSpath,
			String uploadPath)
	{
		// otherwise log4j doesn't shut up...okay maybe it still complains!
	    Logger root = Logger.getRootLogger();
	    root.addAppender(new NullAppender());
	    root.setLevel(Level.OFF);		
		
	    return deposit(fedoraURL, fedoraUsername, fedoraPassword, METSpath, uploadPath);
	}
        
        private static void writeRELSEXT(String objID, String fedoraURL, String uploadPath)
        {
            try{
            URL url = new URL(fedoraURL);

            String host = url.getHost();         

            // Create file 
            FileWriter fstream = new FileWriter(new File(uploadPath) + File.separator + "RELS-EXT.xml");
                BufferedWriter out = new BufferedWriter(fstream);
            out.write("" +
                    "<rdf:RDF xmlns:oai=\"http://www.openarchives.org/OAI/2.0/\"\n" +
                    "xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:rel=\"info:fedora/fedora-system:def/relations-external#\">\n" +
                    "\t<rdf:Description rdf:about=\"info:fedora/"+objID+"\">\n" +
                    "\t\t<oai:itemID>oai:"+ host +":"+ objID +"</oai:itemID>\n" +
                    "\t</rdf:Description>\n" +
                    "</rdf:RDF>");
            //Close the output stream
            out.close();
            }catch (Exception e){//Catch exception if any
              System.err.println("Error: " + e.getMessage());
            }        
        }        

	private static String deposit(String fedoraURL, String fedoraUsername, String fedoraPassword, String METSpath,
			String uploadPath)
	{
		String OBJID = "";
		
		try
		{
			FedoraClient fedora = new FedoraClient(fedoraURL, fedoraUsername, fedoraPassword);
			FedoraAPIM apim = fedora.getAPIM();			
			File METSfile = new File(METSpath);
			FileInputStream fis = new FileInputStream(METSfile);
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			while (fis.available() > 0)
			{
				baos.write(fis.read());
			}
			
			byte[] content = baos.toByteArray();
			OBJID = apim.ingest(content, "metslikefedora1", "Crystallography Dataset Upload");
                        
                        writeRELSEXT(OBJID, fedoraURL, uploadPath);
                        System.out.println("Merged diffraction image metadata into single file for harvest.");
                        
			File folder = new File(uploadPath);
			File[] fileList = folder.listFiles();
			
			System.out.println(fileList.length + " file(s) to be uploaded...");
			System.out.println("");
			
			ArrayList<String> fileNames = new ArrayList<String>();
			
			for (File file : fileList)
			{
				if (file.isFile() && (!file.getName().startsWith(".")))
				{
					System.out.println("Uploading.. " + file.getName());
					String tempURI = fedora.uploadFile(file);
					
                                        String fileNameID = "";
                                        String PREFIX = "XTAL";
                                        String TYPE = "";
                                        
                                        if(file.getName().contains("tar.bz"))
                                        {
                                            TYPE = "DATASET";
                                        }
                                        else if(file.getName().contains(".sca") || file.getName().contains(".mtz"))
                                        {
                                            TYPE = "ANCILLARY";
                                        }
                                        else if(!file.getName().endsWith(".xml"))
                                        {
                                            TYPE = "OTHER";
                                        }
                                        
                                        fileNameID = PREFIX + "_" + TYPE + "_" + file.getName().replace(" ", "_"); // haha

					int i = 0;
					while(fileNames.indexOf(fileNameID) != -1)
					{
						fileNameID = PREFIX + "_" + TYPE + "_" + i + file.getName().replace(" ", "_");
						i++;
					}
					
					fileNames.add(fileNameID);
                                        
                                        if(file.getName().endsWith(".xml"))
                                        {
                                              apim.addDatastream(OBJID, // PID
                                                                file.getName().substring(0, file.getName().length()-4), //fileNameID, // Datastream ID
                                                                new String[] {}, // Alt IDs
                                                                "TARDIS XML: " +
                                                                file.getName().substring(0, file.getName().length()-4), // Label
                                                                true, // Versionable
                                                                "text/xml", // MIME type
                                                                null, // Format URI
                                                                tempURI, // Datastream Location
                                                                "X", // Control Group
                                                                "A", // State
                                                                null, // ChecksumType
                                                                null, // Checksum
                                                                ":)");  
                                        }                                      
                                        else
                                        {
					
                                            apim.addDatastream(OBJID, // PID
                                                            fileNameID, //fileNameID, // Datastream ID
                                                            new String[] {}, // Alt IDs
                                                            file.getName(), // Label
                                                            true, // Versionable
                                                            "", // MIME type
                                                            null, // Format URI
                                                            tempURI, // Datastream Location
                                                            "M", // Control Group
                                                            "A", // State
                                                            null, // ChecksumType
                                                            null, // Checksum
                                                            ":)");
                                        }

				}
			}
					
			System.out.println("");
			System.out.println("Finished uploading files to Fedora Object " + OBJID);

		}
		catch (MalformedURLException ex)
		{
			System.out.println("Malformed URL");
		}
		catch (FileNotFoundException ex)
		{
			System.out.println("File not found");
		}
		catch (RemoteException ex)
		{
			System.out.println("Remote exception");
			
			ex.printStackTrace();
		}		
		catch (IOException ex)
		{
			System.out.println("IO Exception");
                        ex.printStackTrace();
		}
		catch (Exception ex)
		{
			ex.printStackTrace();
		}
		
		return OBJID;
	}

	/**
	 * The commandline implementaton of the {@link DataDepositor} class.
	 * <p>
	 * Run <i>java -jar DataDepositor.jar</i> for instructions on usage.
	 */
	public static void main(String args[])
	{

		if (args.length == 5)
		{
			DataDepositor.deposit(args[0], args[1], args[2], args[3], args[4]);
		}
		else
		{
			System.out
					.println("DataDepositor by Steve Androulakis - Uploads files to a repository into a new object described by a METS XML file");
			System.out.println("");
			System.out.println("USAGE:");
			System.out.println("DataDepositor <fedoraURL> <fedoraUsername> <fedoraPassword> ");
			System.out.println("\t <METSpath> <uploadPath>");
			System.out.println("");
			System.out.println("fedoraURL: The destination repository URL (eg. http://example.org:8080/fedora");
			System.out.println("fedoraUsername: A fedora repository username with upload privilages");
			System.out.println("fedoraPassword: The username's password");
			System.out.println("METSpath: The path to the METS xml file describing the object");
			System.out.println("uploadPath: The path to the files for ingestion");
		}
	}
}